package com.example.demo.service.imply;

import com.aliyuncs.utils.IOUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo.mapper.*;
import com.example.demo.pojo.entity.*;
import com.example.demo.pojo.vo.SubjectVO;
import com.example.demo.service.ISubjectService;
import com.example.demo.utils.ImportQuestion;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class ISubjectServiceImply extends ServiceImpl<SubjectMapper, Subject> implements ISubjectService {
    private final SubjectMapper subjectMapper;
    private final SubjectFileMapper subjectFileMapper;
    private final QuestionLabelMapper questionLabelMapper;
    private final QuestionBankMapper questionBankMapper;
    private final QuestionClassificationMapper questionClassificationMapper;
    private final QuestionFileMapper questionFileMapper;
    private final QuestionCategoryMapper questionCategoryMapper;
    //辅助函数--将题目与文件关联
    void contactFile(int fileId,List<Integer>questionIdList){
        //将题目的列表储存到文件下
        SubjectFile subjectFile=subjectFileMapper.selectById(fileId);
        String nodeId=subjectFile.getNodeId();
        for(int i=0;i<questionIdList.size();i++){
            QuestionFile questionFile=new QuestionFile();
            questionFile.setNodeId(nodeId);
            questionFile.setQuestionId(questionIdList.get(i));
            questionFile.setFileId(fileId);
            questionFileMapper.insert(questionFile);
        }
    }
    //辅助函数--将文件导入的题目与知识点表关联
    void contactClassification(List<Integer>questionIdList,String labelNodeId){
        for(int i=0;i<questionIdList.size();i++){
            QuestionBank question=questionBankMapper.selectById(questionIdList.get(i));
            if(question!=null){
                String labelName=question.getLabel();
                if(labelName!=null){
                    String[] labelNames = labelName.split(";");
                    for(int j=0;j<labelNames.length;j++) {
                        QueryWrapper<QuestionLabel>queryWrapper=new QueryWrapper<>();
                        queryWrapper.like("name",labelNames[j]);
                        queryWrapper.likeRight("node_id",labelNodeId);
                        //进行名字的模糊查找，同时通过根id指定某个学科下的知识点
                        List<QuestionLabel>questionLabelList=questionLabelMapper.selectList(queryWrapper);
//  0                  List<QuestionLabel> questionLabelList = questionLabelMapper.searchQuestionLabel(labelNames[j]);
                        QuestionLabel questionLabel;
                        System.out.println(question);
                        //题型存在才进行下一步操作
                        if (!questionLabelList.isEmpty()) {
                            questionLabel = questionLabelList.get(0);
                            //获得物化表相关信息
                            int questionLabelId = questionLabel.getId();
                            String nodeId = questionLabel.getNodeId();
                            int questionBankId = question.getId();
                            QuestionClassification questionClassification = new QuestionClassification();
                            questionClassification.setQuestionBankId(questionBankId);
                            questionClassification.setQuestionLabelId(questionLabelId);
                            questionClassification.setNodeId(nodeId);
                            questionClassificationMapper.insert(questionClassification);
                        }
                    }
                }else{
                    //增添学科处理
                    QuestionClassification questionClassification = new QuestionClassification();
                    questionClassification.setQuestionBankId(question.getId());
                    questionClassification.setQuestionLabelId(1);
                    questionClassification.setNodeId("1-");
                    questionClassificationMapper.insert(questionClassification);
                }
            }
        }
    }
    void contactClassification(List<Integer>questionIdList,int labelNodeId){
        int totalInsert=0;
        int notLabel=0;
        List<Integer>insertIdList=new ArrayList<>();
        for(int i=0;i<questionIdList.size();i++){
            QuestionBank question=questionBankMapper.selectById(questionIdList.get(i));
            if(question!=null){
                String labelName=question.getLabel();
                if(labelName!=null){
                    List<String> labelNameList = Arrays.stream(labelName.split(";"))
                            .collect(Collectors.toList());
                    List<String>nodeIdList=new ArrayList<>();
                    HashMap<String,Integer> hashMapClassification=new HashMap<>();
                    int saveNumberForTotalNumber=0;
                    int maxTotalNumber=0;
                    //第一层遍历所有的题型
                    for(int j=0;j<labelNameList.size();j++) {
                        QueryWrapper<QuestionLabel>queryWrapper=new QueryWrapper<>();
                        queryWrapper.eq("name",labelNameList.get(j));
                        queryWrapper.likeRight("node_id",1+"-");
                        //进行名字的模糊查找，同时通过根id指定某个学科下的知识点
                        List<QuestionLabel>questionLabelList=questionLabelMapper.selectList(queryWrapper);
                        System.out.println(questionLabelList);
                        //题型存在才进行下一步操作
                        if (!questionLabelList.isEmpty()) {
                            QuestionLabel questionLabel = questionLabelList.get(0);
                            int category=1;
                            int questionLabelId = questionLabel.getId();
                            String nodeId = questionLabel.getNodeId();
                            //逻辑为查找已经储存过的题型关系中如果新添加的属于更深层的或者比先前低，而做出不同的category设置
                            //第二层:根据当前处理的label去判断前面已经储存的label与之的关系
                            for(int k=0;k<nodeIdList.size();k++){
                                String beforeNodeId = nodeIdList.get(k);
                                if(beforeNodeId.startsWith(nodeId)){
                                    System.out.println(nodeId+"----"+beforeNodeId);
                                    category=0; //表示这一题只提供关系
                                }else if(nodeId.startsWith(beforeNodeId)){
                                    int beforeId=hashMapClassification.get(beforeNodeId);
                                    QuestionClassification updateClassification=questionClassificationMapper.selectById(beforeId);
                                    //先前的题只提供关系
                                    UpdateWrapper<QuestionClassification>updateClassificationWrapper=new UpdateWrapper<>();
                                    updateClassification.setClassificationCategory(0);
                                    updateClassificationWrapper.eq("id",updateClassification.getId());
                                    questionClassificationMapper.update(updateClassification,updateClassificationWrapper);
                                }else{ //category设置为2
                                    category=3;
                                    //检查到不一样,需要将前面所有的都进行一次更新---第三层for循环
                                    for(int m=0;m<nodeIdList.size();m++){
                                        String nodeIdFor=nodeIdList.get(m);
                                        int beforeId=hashMapClassification.get(nodeIdFor);
                                        QuestionClassification questionClassification=questionClassificationMapper.selectById(beforeId);
                                        if(questionClassification.getClassificationCategory()!=0) { //不等于0才有意义
                                            //原来为0的不进入处理，主要在处理1上
                                            UpdateWrapper<QuestionClassification> updateClassificationWrapper = new UpdateWrapper<>();
                                            questionClassification.setClassificationCategory(2);
                                            updateClassificationWrapper.eq("id", questionClassification.getId());
                                            questionClassificationMapper.update(questionClassification, updateClassificationWrapper);
                                            saveNumberForTotalNumber = saveNumberForTotalNumber + 1; //表示修改一个为2则将其记录
                                        }
                                    }
                                    System.out.println("检查出对2进行替换--替换的number"+saveNumberForTotalNumber);
                                }
                            }
                            if(saveNumberForTotalNumber>maxTotalNumber){
                                maxTotalNumber=saveNumberForTotalNumber;
                            }
                            int questionBankId = question.getId();
                            QuestionClassification questionClassification = new QuestionClassification();
                            questionClassification.setClassificationCategory(category);
                            questionClassification.setQuestionBankId(questionBankId);
                            questionClassification.setQuestionLabelId(questionLabelId);
                            questionClassification.setNodeId(nodeId);
                            questionClassificationMapper.insert(questionClassification);
                            int classificationId=questionClassification.getId();
                            nodeIdList.add(nodeId);
                            hashMapClassification.put(nodeId,classificationId);
                        }
                    }
                    insertIdList.add(question.getId());
                    totalInsert=totalInsert+1;
                }else{
                    //增添学科处理---当没找到与之相对于的题型，默认划分到根知识点下
                    notLabel=notLabel+1;
                    totalInsert=totalInsert+1;
//                    System.out.println("当前进行的是无label插入--插入的对象是"+question);
                    QuestionClassification questionClassification = new QuestionClassification();
                    questionClassification.setQuestionBankId(question.getId());
                    questionClassification.setQuestionLabelId(labelNodeId);
                    questionClassification.setNodeId("1-");
                    questionClassification.setClassificationCategory(1);
                    questionClassificationMapper.insert(questionClassification);
                    //
                    insertIdList.add(question.getId());
                }
            }
        }
        System.out.println("成功建立联系的题目是"+totalInsert);
        System.out.println("没有题型的题目数量"+notLabel);
        System.out.println("成功进入的bankId"+insertIdList.size());
    }
    //处理函数--初始化学科表
    @Override
    public List<SubjectVO> initSubject() {
        List<Subject>subjectList=subjectMapper.initSubject();
        List<SubjectVO>result=new ArrayList<SubjectVO>();
        for(Subject subject : subjectList){
            SubjectVO subjectVO=new SubjectVO();
            subjectVO.initSubject(subject);
            result.add(subjectVO);
        }
        return result;
    }
    //处理函数--根据id进行查找学科
    @Override
    public Subject searchById(@RequestBody  int id) {
        return subjectMapper.selectById(id);
    }
    //处理函数--添加学科
    @Override
    public int addSubject(Subject subject) {
        if(subject==null){
            return 0;
        }else{
            //获取fileId和labelId
            //更新fill并且获取id
            String subjectName=subject.getSubjectName();
            String createUser=subject.getCreateUser();
            SubjectFile file=new SubjectFile();
            file.setFileName(subjectName);
            file.setCreateUser(createUser);
            file.setParentId(0);
            file.setLevel(0);
            subjectFileMapper.insert(file);
            int fileId=file.getId();
            String fileNodeId=String.valueOf(fileId)+'-';
            file.setNodeId(fileNodeId);
            UpdateWrapper<SubjectFile> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("id", fileId);
            subjectFileMapper.update(file, updateWrapper);
            //更新label并且获取id
            QuestionLabel questionLabel=new QuestionLabel();
            questionLabel.setLevel(0);
            questionLabel.setName(subjectName);
            questionLabel.setParentId(0);
            questionLabelMapper.insert(questionLabel);
            int questionId=questionLabel.getId();
            String questionNodeId=String.valueOf(questionId)+'-';
            questionLabel.setNodeId(questionNodeId);
            UpdateWrapper<QuestionLabel> questionLabelUpdateWrapper = new UpdateWrapper<>();
            questionLabelUpdateWrapper.eq("id", questionId);
            questionLabelMapper.update(questionLabel,questionLabelUpdateWrapper);
            subject.setFileId(fileId);
            subject.setLabelId(questionId);
        }
        subjectMapper.insert(subject);
        return 1;
    }
    //处理函数--上传文件
    @Override
    public void uploadFile(MultipartFile file,int subjectId,int fileId) {
        ImportQuestion temp=new ImportQuestion(file);
        List<String[]> questionList = temp.getQuestionList();
        List<QuestionBank>questionBankList = new ArrayList<>();
        List<Integer>idList=new ArrayList<>();
        if(questionList!=null){
            System.out.println("this is");
            questionList.remove(0);
            for(String[] question : questionList){
                if(question.length<1){
                    break;
                }
                QuestionBank questionBank=new QuestionBank();
                String tempCategory=question[0];
                if(tempCategory==null){
                    continue;
                }
                Integer categoryId=questionCategoryMapper.searchCategory(tempCategory);
                String questionName=question[1];
                String parse=question[3];
                String htmlName=ImportQuestion.formatJavaClass(questionName);
                String htmlParse=ImportQuestion.formatJavaClass(parse);
                questionBank.setCategory(categoryId);
                questionBank.setName(questionName);
                questionBank.setCorrectAnswer(question[2]);
                questionBank.setParse(question[3]);
                questionBank.setDifficulty(question[4]);
                questionBank.setHtmlName(htmlName);
                questionBank.setHtmlParse(htmlParse);
                //处理题型
                String tempLabelName;
                try {
                    tempLabelName=question[5];
                }catch (Exception e){
                    questionBankList.add(questionBank);
                    continue;
                }
                questionBank.setLabel(tempLabelName);
                double answerNumber;
                StringBuilder option= new StringBuilder();
                StringBuilder htmlOption=new StringBuilder();
                try {
                    answerNumber=Double.parseDouble(question[6]);
                    questionBank.setAnswerNumber(answerNumber);
                    for(int i=7;i<7+answerNumber;i++){
                        try
                        {
                            String oneOption=question[i];
                            if (oneOption.contains("\n")) {
                                break;
                            }
                            option.append(oneOption);
                            htmlOption.append(ImportQuestion.formatJavaClass(oneOption));
                            htmlOption.append('|');
                            option.append('|');
                        }
                        catch (Exception e)
                        {
                            break;
                        }
                    }
                }catch (Exception e){
                    questionBank.setOptions(String.valueOf(option));
                    questionBankList.add(questionBank);
                    continue;
                }
                questionBank.setOptions(String.valueOf(option));
                questionBank.setHtmlOption(String.valueOf(htmlOption));
                questionBankList.add(questionBank);
            }
            //for循环结束,将列表中的题目添加到数据库中
            for(int i=0;i<questionBankList.size();i++){
                QuestionBank tempBank=questionBankList.get(i);
                questionBankMapper.insert(tempBank);
                idList.add(tempBank.getId());
            }
        }
        System.out.println("一共插入了xxx条数据"+idList.size());
        System.out.println("结束题目的插入");
        //导入题目后要在文件关联表和知识点关联表完善信息
        Subject subject=subjectMapper.selectById(subjectId);
        int labelId=subject.getLabelId();
        contactFile(fileId,idList);
        System.out.println("结束与文件的关联");
        contactClassification(idList,labelId);
    }

    @Override
    public void downTemplateInfo(HttpServletResponse response) {
        try {
            downloadFile("F:\\web\\juanzi\\src\\main\\resources\\static\\demo.xls", response);
        } catch (Exception e) {
            log.error("文件下载出错:" + e.getMessage() + " 原路径：" + "../../../../resources/static/demo.xls");
            e.printStackTrace();
        }
    }
    public void downloadFile(String filePath, HttpServletResponse response) throws Exception{
        File f = new File(filePath);
        if (!f.exists()) {
            throw new FileNotFoundException("找不到文件");
        }
        System.out.println("下载");
        BufferedInputStream br = new BufferedInputStream(new FileInputStream(f));
        byte[] buf = new byte[1024];
        int len = 0;
        response.reset();
        response.setContentType("application/x-msdownload");
        response.setCharacterEncoding("utf-8");;
        response.setHeader("Content-Disposition", "attachment; filename=" + "213");

        OutputStream out = response.getOutputStream();
        while ((len = br.read(buf)) > 0)
            out.write(buf, 0, len);
        IOUtils.closeQuietly(br);
        IOUtils.closeQuietly(out);
    }
}
